package com.semidata.trp.material.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import com.semidata.rtd.core.log.Logger;
import com.semidata.trp.material.config.Config;

public class MaterialService {
    private static Config config = Config.getConfig();

    public MaterialService() {

    }

    public static String getMD5(byte[] source) {
        String s = null;
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(source);
            byte tmp[] = md5.digest();
            char str[] = new char[16 * 2];
            int k = 0;
            for (int i = 0; i < 16; i++) {
                byte byte0 = tmp[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            s = new String(str);
        } catch (NoSuchAlgorithmException e) {
            Logger.log("ERROR", e);
        }

        return s;
    }

    public static String getUrl(String code, String type) {
        StringBuffer sb = new StringBuffer();
        sb.append(config.getProxyHost());
        if (config.getProxyHost().endsWith("/")) {
            if (config.getUrlPrefix().startsWith("/"))
                sb.append(config.getUrlPrefix().substring(1));
            else
                sb.append(config.getUrlPrefix());
        } else {
            if (config.getUrlPrefix().startsWith("/"))
                sb.append(config.getUrlPrefix());
            else
                sb.append('/').append(config.getUrlPrefix());
        }

        if (config.getUrlPrefix().endsWith("/"))
            sb.append("review/");
        else
            sb.append("/review/");

        sb.append(code);
        sb.append(".");
        sb.append(type);
        return sb.toString();

    }

    public static String upload(byte[] data, String type) {

        int size = data.length;

        if (size == 0) {
            Logger.log("ERROR", "image file size is : 0");
            return "No data is acquired";
        }
        String code = getMD5(data);
        if (code == null || code.length() == 0)
            return "MD5 code fail";
        String url = "";
        FileChannel channel = null;
        FileLock lock = null;
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(getFileName(code, type));
            channel = fos.getChannel();
            lock = channel.lock();
            fos.write(data, 0, size);
            url = getUrl(code, type);
        } catch (Exception e) {
            e.printStackTrace();
            Logger.log("ERROR", e);
        } finally {
            if (lock != null) {
                try {
                    lock.release();
                    lock.close();
                    lock = null;
                } catch (IOException e) {
                    e.printStackTrace();
                    Logger.log("ERROR", e);
                }
            }
            if (channel != null) {
                try {
                    channel.close();
                    channel = null;
                } catch (IOException e) {
                    e.printStackTrace();
                    Logger.log("ERROR", e);
                }
            }
            if (fos != null) {
                try {
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    Logger.log("ERROR", e);
                }

            }
        }
        if (url.length() != 0)
            return url;
        else
            return "ERROR";

    }

    public static File getFileName(String code, String type) {
        File file = new File(config.getMaterialPath());
        file = new File(file, code.substring(0, 1));
        file = new File(file, code.substring(1, 2));
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(file, code + '.' + type);
        return file;
    }
    
    private static File getFileName(String filename) {
        if (filename.length() < 2)
            return null;
        File file = new File(config.getMaterialPath());
        file = new File(file, filename.substring(0, 1));
        file = new File(file, filename.substring(1, 2));
        file = new File(file, filename);
        return file;
    }

    public static boolean remove(String filename) {

        File file = getFileName(filename);
        if (file == null)
            return false;

        if (file.isFile())
            file.delete();
        else
            return false;

        if (file.exists()) {
            return false;
        }

        return true;
    }

    public static byte[] review(String filename) {
        String code = filename.substring(0, filename.indexOf('.'));
        String end = filename.substring(filename.indexOf('.') + 1);
        File file = getFileName(code, end);
        Logger.log("DEBUG", "filename : " + file.getAbsolutePath());

        if (!file.isFile())
            return null;
        FileInputStream fis = null;
        byte[] data = null;
        try {
            fis = new FileInputStream(file);
            int size = fis.available();
            data = new byte[size];
            fis.read(data, 0, size);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            Logger.log("ERROR", e);
        } catch (IOException e) {
            e.printStackTrace();
            Logger.log("ERROR", e);
        } catch (Exception e) {
            e.printStackTrace();
            Logger.log("ERROR", e);
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
                Logger.log("ERROR", e);
            }

        }
        Logger.log("DEBUG", "data size : " + data.length);
        return data;
    }

}
